const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const generateFile = require('generate-file-webpack-plugin');
const path = require('path');
const fs = require('fs');

const cwd = process.cwd();

const etbResourceFolderPath = path.join(cwd, 'public', 'etb', 'OEBPS', 'resources');
const etbResourceFiles = [];
fs.readdirSync(etbResourceFolderPath, { withFileTypes: true }).forEach((entry) => {
  if (entry.isFile()) etbResourceFiles.push(entry.name);
});

// 控件的最终的package.json文件内容是从package.json中的widgetProperties字段值生成的
const packageJson = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), { encoding: 'utf8' }));
const widgetProperties = packageJson.widgetProperties;
widgetProperties.version = packageJson.version;

const translations = JSON.parse(fs.readFileSync(
  path.join(cwd, 'src', '_locales', 'zh-CN', 'package.json'),
  { encoding: 'utf8' },
));

const pageId = 'default-sTJ4AGn';
const widgetId = `${widgetProperties.name}-123456`;
const widgetDistDir = path.join(cwd, 'dist', 'etb', 'OEBPS', 'controls', widgetProperties.name);
const pageDir = path.join(cwd, 'dist', 'etb', 'OEBPS', 'pages', pageId);

const tobeCopiedWidgetFiles = [];
['initData', 'options', 'signals', 'slots'].forEach((prop) => {
  if (widgetProperties[prop]) {
    tobeCopiedWidgetFiles.push({
      from: path.join(cwd, 'src', widgetProperties[prop]),
      to: path.join(widgetDistDir, widgetProperties[prop])
    });
  }
});

module.exports = {
  context: cwd,
  entry: {
    main: path.join(cwd, 'container/main.ts'),
    [`etb/OEBPS/controls/${widgetProperties.name}/main`]: path.join(cwd, 'src/main.ts'),
    [`etb/OEBPS/controls/${widgetProperties.name}/propEditors/preset/main`]: path.join(cwd, 'src/propEditors/preset/main.ts'),
  },
  output: {
    path: path.join(cwd, 'dist'),
    filename: '[name].js',
    library: {
      name: '[name]',
      type: 'umd',
      umdNamedDefine: false
    },
    libraryExport: 'default',
  },
  resolve: {
    alias: {
      '@': path.resolve(cwd, 'src'),
    },
    extensions: [
      '.ts',
      '.js',
      '.vue',
      '.json'
    ],
  },
  target: 'browserslist',
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader',
            options: { hotReload: false }
          }
        ]
      },
      {
        test: /\.tpl$/,
        use: [
          {
            loader: 'dot-loader',
            options: {}
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env']
            ]
          }
        }
      },
      {
        test: /\.ts$/,
        exclude: /(node_modules)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env']
              ]
            }
          },
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/],
            },
          }
        ],
      },
      // this will apply to both plain `.css` files
      // AND `<style>` blocks in `.vue` files
      {
        test: /\.css$/,
        use: [
          // 'vue-style-loader',
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              url: false
            }
          },
        ]
      },
      {
        test: /\.less$/,
        use: [
          // 'vue-style-loader',
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              url: false
            }
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true,
                modifyVars: {
                  // 'public-path': `~'${publicPath}'`, // less variable escaping
                },
              }
            }
          }
        ]
      }
    ]
  },
  externals: {
    "vue": "vue",
    "ant-design-vue": "ant-design-vue",
    "pinia": "pinia",
    "WidgetBase": "WidgetBase",
    "jquery": "jquery",
    "base": "base"
  },
  devServer: {
    static: [path.join(cwd, 'dist')],
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        if (pathData.chunk.name === `etb/OEBPS/controls/${widgetProperties.name}/main`) {
          return `etb/OEBPS/controls/${widgetProperties.name}/resources/css/main.css`
        }
        return `${pathData.chunk.name}.css`;
      }
    }),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: path.join(cwd, 'public', 'index.html'),
          to: path.join(cwd, 'dist', 'index.html')
        },
        {
          from: path.join(cwd, 'public', 'etb'),
          to: path.join(cwd, 'dist', 'etb')
        },
        {
          from: path.join(cwd, 'node_modules', '@learnware', 'wcpe', 'dist'),
          to: path.join(cwd, 'dist', 'wcpe')
        },
        {
          from: path.join(cwd, 'node_modules', '@learnware', 'reader', 'dist'),
          to: path.join(cwd, 'dist', 'reader')
        },
        {
          from: path.join(cwd, 'node_modules', '@learnware', 'ueditor'),
          to: path.join(cwd, 'dist', 'ueditor')
        },
        {
          from: path.join(cwd, 'public', 'require.js'),
          to: path.join(cwd, 'dist', 'require.js')
        },
        {
          from: path.join(cwd, 'src', 'resources'),
          to: path.join(widgetDistDir, 'resources')
        },
        {
          from: path.join(cwd, 'src', '_locales'),
          to: path.join(widgetDistDir, '_locales')
        },
        ...tobeCopiedWidgetFiles
      ]
    }),
    // 生成控件的 package.json 文件
    generateFile({
      file: path.join(widgetDistDir, 'package.json'),
      content: JSON.stringify(widgetProperties)
    }),
    // 生成控件的 package.json 文件
    generateFile({
      file: path.join(cwd, 'dist', 'etb-resource-files.js'),
      content: 'window.ETB_RESOURCE_FILES = ' + JSON.stringify(etbResourceFiles)
    }),
    // 生成 etb 中的 page.html 文件
    generateFile({
      file: path.join(pageDir, 'page.html'),
      content: () => {
        const initDataFilePath = path.join(cwd, 'src', widgetProperties.initData);
        const widgetInitData = JSON.parse(fs.readFileSync(initDataFilePath, { encoding: 'utf8' }));
        if (!widgetInitData.width) widgetInitData.width = 400;
        if (!widgetInitData.height) widgetInitData.height = 300;
        return `
          <div
            data-id="${widgetId}"
            data-name="${translations.package.displayName}"
            data-visible="true"
            data-control="${widgetProperties.name}"
            data-show="native"
            data-hide="native"
            style="
              position:absolute;
              z-index:1;
              width:${widgetInitData.width}px;
              height:${widgetInitData.height}px;
              top:20px;
              left:20px;
            "
          ></div>
        `.replace(/\n/g, ' ').replace(/\s+/g, ' ');
      }
    }),
    // 生成 etb 中的 controls-data.json 文件
    generateFile({
      file: path.join(pageDir, 'controls-data.json'),
      content: () => {
        const initDataFilePath = path.join(cwd, 'src', widgetProperties.initData);
        const widgetInitData = JSON.parse(fs.readFileSync(initDataFilePath, { encoding: 'utf8' }));
        if (!widgetInitData.width) widgetInitData.width = 400;
        if (!widgetInitData.height) widgetInitData.height = 300;
        const pageControlsData = { system: {} };
        pageControlsData[widgetId] = widgetInitData;
        return JSON.stringify(pageControlsData);
      }
    })
  ],
  devtool: "hidden-source-map"
}
